package com.example.testapp.domain.util

/**
 * 雪花ID生成器，用于生成全局唯一ID
 * 
 * 雪花算法结构：
 * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000
 * 1位符号位 - 41位时间戳 - 5位数据中心ID - 5位机器ID - 12位序列号
 */
class SnowflakeIdGenerator private constructor(dataCenterId: Long, workerId: Long) {
    // 开始时间戳 (2023-01-01)
    private val twepoch = 1672531200000L

    // 各部分占用的位数
    private val dataCenterIdBits = 5L
    private val workerIdBits = 5L
    private val sequenceBits = 12L

    // 各部分最大值
    private val maxDataCenterId = -1L xor (-1L shl dataCenterIdBits.toInt())
    private val maxWorkerId = -1L xor (-1L shl workerIdBits.toInt())
    private val sequenceMask = -1L xor (-1L shl sequenceBits.toInt())

    // 各部分向左的位移
    private val workerIdShift = sequenceBits
    private val dataCenterIdShift = sequenceBits + workerIdBits
    private val timestampLeftShift = sequenceBits + workerIdBits + dataCenterIdBits

    private val dataCenterId: Long
    private val workerId: Long
    private var sequence = 0L
    private var lastTimestamp = -1L

    init {
        require(!(dataCenterId > maxDataCenterId || dataCenterId < 0)) {
            "Data center ID can't be greater than $maxDataCenterId or less than 0"
        }
        require(!(workerId > maxWorkerId || workerId < 0)) {
            "Worker ID can't be greater than $maxWorkerId or less than 0"
        }
        this.dataCenterId = dataCenterId
        this.workerId = workerId
    }

    /**
     * 获取下一个ID
     * @return 生成的ID
     */
    @Synchronized
    fun nextId(): Long {
        var timestamp = timeGen()

        // 如果当前时间小于上一次ID生成的时间戳，说明系统时钟回退过
        if (timestamp < lastTimestamp) {
            throw RuntimeException("Clock moved backwards. Refusing to generate ID")
        }

        // 如果是同一时间生成的，则进行毫秒内序列
        if (lastTimestamp == timestamp) {
            sequence = (sequence + 1) and sequenceMask
            // 毫秒内序列溢出
            if (sequence == 0L) {
                // 阻塞到下一个毫秒，获得新的时间戳
                timestamp = tilNextMillis(lastTimestamp)
            }
        } else {
            // 时间戳改变，毫秒内序列重置
            sequence = 0L
        }

        // 上次生成ID的时间戳
        lastTimestamp = timestamp

        // 移位并通过或运算拼到一起组成64位的ID
        return ((timestamp - twepoch) shl timestampLeftShift.toInt()) or
                (dataCenterId shl dataCenterIdShift.toInt()) or
                (workerId shl workerIdShift.toInt()) or
                sequence
    }

    /**
     * 阻塞到下一个毫秒，直到获得新的时间戳
     * @param lastTimestamp 上次生成ID的时间戳
     * @return 当前时间戳
     */
    private fun tilNextMillis(lastTimestamp: Long): Long {
        var timestamp = timeGen()
        while (timestamp <= lastTimestamp) {
            timestamp = timeGen()
        }
        return timestamp
    }

    /**
     * 返回当前时间的毫秒数
     * @return 当前时间的毫秒数
     */
    private fun timeGen(): Long {
        return System.currentTimeMillis()
    }

    companion object {
        @Volatile
        private var instance: SnowflakeIdGenerator? = null

        /**
         * 获取单例实例
         * @param dataCenterId 数据中心ID
         * @param workerId 机器ID
         * @return 雪花ID生成器实例
         */
        @JvmStatic
        fun getInstance(dataCenterId: Long, workerId: Long): SnowflakeIdGenerator {
            return instance ?: synchronized(this) {
                instance ?: SnowflakeIdGenerator(dataCenterId, workerId).also { instance = it }
            }
        }
    }
} 